﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.Contracts;
using System.Windows;

namespace OpenLS.Spreadsheet
{
    class CellsWindowView
    {
        private readonly CellsWindow _window;
        private readonly Predicate<Cell> _predicate;
        private List<Cell> list;
        
        public CellsWindowView(CellsWindow window, Predicate<Cell>predicate)
        {
            Contract.Requires(window != null);
            Contract.Requires(predicate != null);
            _window = window;
            _predicate = predicate;
            this.list = new List<Cell>(_window.GetCells());
            Hook();
#if DEBUG
            if (Application.Current != null)
                Application.Current.Exit += new ExitEventHandler((sender, e) => {
                                                                                GC.SuppressFinalize(this);
            });
#endif
        }

        private void Hook()
        {
            _window.CellsAdded += new EventHandler<ListEventArgs<Cell>>(_window_CellAdded);
            _window.CellsRemoved += new EventHandler<ListEventArgs<Cell>>(_window_CellRemoved);
            _window.Cleared += new EventHandler(_window_Cleared);
        }


        void _window_Cleared(object sender, EventArgs e)
        {
            list.Clear();
        }

        void _window_CellRemoved(object sender, ListEventArgs<Cell> e)
        {
            foreach (var cell in Enumerable.Where(e.Items, c => _predicate(c)))
            {
                list.Remove(cell);
            }
        }

        void _window_CellAdded(object sender, ListEventArgs<Cell> e)
        {
            foreach (var cell in Enumerable.Where(e.Items, c => _predicate(c)))
            {
                list.Add(cell);
            }
        }

        private void Unhook()
        {
            _window.CellsAdded -= new EventHandler<ListEventArgs<Cell>>(_window_CellAdded);
            _window.CellsRemoved -= new EventHandler<ListEventArgs<Cell>>(_window_CellRemoved);
            _window.Cleared -= new EventHandler(_window_Cleared);
        }
        public void Dispose()
        {
#if DEBUG
            _disposed = true;
#endif
            Unhook();
        }

#if DEBUG
        internal bool _disposed;
        ~CellsWindowView()
        {
            Contract.Assert(_disposed);
        }
#endif

        public IEnumerable<Cell> GetCells()
        {
            return list;
        }
    }
}